package tool.test.mssql.db;

import org.ini4j.Ini;
import tool.test.mssql.Runner;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public class ConnectionPool {
    private List<Connection> cs = new ArrayList<>();
    private int size;
    private int initCount;

    public ConnectionPool(int size, int initCount) {
        this.size = size;
        this.initCount = initCount;
    }

    private void createConnect() throws SQLException, ClassNotFoundException {
        Runner.initIniConfig();
        if (Runner.ini != null && Runner.ini.containsKey("mssql")) {
            Ini.Section section = Runner.ini.get("mssql");
            String jdbcUrl, user, password;
            if (section.containsKey("poolSize")) {
                size = Integer.valueOf(section.get("poolSize"));
            }
            if (section.containsKey("initPoolSize")) {
                initCount = Integer.valueOf(section.get("initPoolSize"));
            }
            if (section.containsKey("jdbcUrl")) {
                jdbcUrl = section.get("jdbcUrl");
            } else {
                throw new SQLException("parameter jdbcUrl is empty.");
            }
            if (section.containsKey("user")) {
                user = section.get("user");
            } else {
                throw new SQLException("parameter user is empty.");
            }
            if (section.containsKey("password")) {
                password = section.get("password");
            } else {
                throw new SQLException("parameter password is empty.");
            }
            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
            Connection c = DriverManager.getConnection(jdbcUrl, user, password);
            System.out.println("Connecting " + cs.size() + " connection.");
            cs.add(c);
        } else {
            System.out.println("database parameters is empty.");
        }
    }

    public synchronized Connection getConnection() throws InterruptedException {
        Connection c = null;
        int number = 1;
        while (true) {
            while (cs.isEmpty()) {
                if (this.initCount < this.size) {
                    try {
                        createConnect();
                    } catch (ClassNotFoundException | SQLException e) {
                        e.printStackTrace();
                        System.out.println("第" + (number++) + "次，请求失败...");
                        if (number > 3) {
                            break;
                        }
                        try {
                            Thread.sleep(500);
                        } catch (Exception ex) {
                        }
                    }
                } else {
                    this.wait();
                }
            }
            if (number > 3) {
                System.out.println("请求失败，退出");
                break;
            }
            if (cs.isEmpty()) continue;

            c = cs.remove(0);
            try {
                Statement statement = c.createStatement();
                statement.execute("SELECT 'AA'");
                statement.close();
                break;
            } catch (SQLException ex) {
                ex.printStackTrace();
                System.out.println("Connection is timeout, reconnecting...");
            }
        }
        return c;
    }

    public synchronized void returnConnection(Connection c) {
        try {
            Statement statement = c.createStatement();
            statement.execute("SELECT @@VERSION");
            statement.close();
            //使用完给回连接池中
            cs.add(c);
            //唤醒wait告诉它有新的连接池可用
            this.notifyAll();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }
}
